home *** CD-ROM | disk | FTP | other *** search
/ Usenet 1993 July / InfoMagic USENET CD-ROM July 1993.ISO / sources / misc / volume8 / packdisk < prev    next >
Encoding:
Text File  |  1989-10-08  |  17.5 KB  |  643 lines

  1. Newsgroups: comp.sources.misc
  2. subject: v08i093: System V disk compactor
  3. from: allbery@uunet.UU.NET (Brandon S. Allbery - comp.sources.misc)
  4. Reply-To: andy@csvax.caltech.edu (Andy Fyfe)
  5.  
  6. Posting-number: Volume 8, Issue 93
  7. Submitted-by: andy@csvax.caltech.edu (Andy Fyfe)
  8. Archive-name: packdisk
  9.  
  10. The hard disk on my 3b1 reached an intolerable level of fragmentation,
  11. so I wrote this program to do an in situ reorganization of the disk.
  12. The end result is all files and directories are contiguous, and the
  13. free space is collected at the end of the disk.  The program makes great
  14. efforts to leave the disk in a "safe" state at all times (with the
  15. execption of the free list, which isn't rebuilt until the end, though
  16. an "fsck -s" will rebuild it should the program be terminated early).
  17.  
  18. Though this program was developed on a 3b1, it was written with
  19. portability in mind (yes, I know -- you can stop laughing now!).
  20. Perhaps other systems with the System V file system (inherited from
  21. V7?) can also use the program, or adapt it to their needs.
  22.  
  23. This program has been successfully run on my system.  I don't promise
  24. that it will run correctly on any system -- including another 3b1.
  25. Use it at your own risk!
  26.  
  27. Andy Fyfe
  28.             andy@csvax.caltech.edu
  29.             wjafyfe@caltech.bitnet
  30.             andy@cit-vax.UUCP    (...!ames!elroy!cit-vax!andy)
  31.  
  32. #! /bin/sh
  33. # This is a shell archive.  Remove anything before this line, then unpack
  34. # it by saving it into a file and typing "sh file".  To overwrite existing
  35. # files, type "sh file -c".  You can also feed this as standard input via
  36. # unshar, or by typing "sh <file", e.g..  If this archive is complete, you
  37. # will see the following message at the end:
  38. #        "End of shell archive."
  39. # Contents:  README COPYRIGHT Makefile packdisk.c
  40. # Wrapped by andy@marmot on Sat Oct  7 19:51:41 1989
  41. PATH=/bin:/usr/bin:/usr/ucb ; export PATH
  42. if test -f 'README' -a "${1}" != "-c" ; then 
  43.   echo shar: Will not clobber existing file \"'README'\"
  44. else
  45. echo shar: Extracting \"'README'\" \(1486 characters\)
  46. sed "s/^X//" >'README' <<'END_OF_FILE'
  47. XThis program rearranges the files and directories on a disk
  48. Xso that they appear contiguously.  This is to counteract the
  49. Xfragmentation that occurs after a time under System V.  After
  50. Xthe program finishes all the free space will be collected at
  51. Xthe end of the disk.
  52. X
  53. XThis program was written on an AT&T 3b1 (running unix version 3.5).
  54. XWhile the program was written with portability in mind, it is *not*
  55. Xguaranteed to run on *any* machine, not even the 3b1.  It has,
  56. Xhowever, worked for me.
  57. X
  58. XYou should run fsck before running this program, and again after
  59. Xit's done, just to be sure!
  60. X
  61. XThe program is *slow*.  However, the disk is updated after *every*
  62. Xblock is moved, so the file system should be in a consistent state
  63. Xif the program is halted for any reason (except for the free list,
  64. Xwhich is not rebuilt until the very end).
  65. X
  66. XI don't guarantee that this program won't destroy your disk.
  67. XMake sure you have a backup just in case!!!
  68. X
  69. XTo run the program, simply give the disk device as its only
  70. Xargument.  The program will normally ensure that the given name
  71. Xis a character special device.  If compiled with '-DDEBUG', this
  72. Xcheck is eliminated.  This allows, for example, you to "dd" a
  73. Xfloppy to a disk file (say /tmp/disk) and then run the program
  74. Xwith '/tmp/disk' as its argument.  When running on a real disk,
  75. Xthe disk in question *must* *not* be mounted!!!
  76. X
  77. XRemember:  THIS PROGRAM IS POTENTIALLY VERY DANGEROUS.  Use it
  78. Xat your own risk.
  79. X
  80. X                Andrew Fyfe
  81. X                andy@csvax.caltech.edu
  82. END_OF_FILE
  83. if test 1486 -ne `wc -c <'README'`; then
  84.     echo shar: \"'README'\" unpacked with wrong size!
  85. fi
  86. # end of 'README'
  87. fi
  88. if test -f 'COPYRIGHT' -a "${1}" != "-c" ; then 
  89.   echo shar: Will not clobber existing file \"'COPYRIGHT'\"
  90. else
  91. echo shar: Extracting \"'COPYRIGHT'\" \(1026 characters\)
  92. sed "s/^X//" >'COPYRIGHT' <<'END_OF_FILE'
  93. X/*
  94. X * Copyright (c) Andrew Fyfe, 1989
  95. X * All rights reserved.
  96. X * Written by Andrew Fyfe.
  97. X *
  98. X * Permission is granted to anyone to use this software for any purpose on
  99. X * any computer system, and to alter it and redistribute it freely, subject
  100. X * to the following restrictions:
  101. X *
  102. X * 1. The author is not responsible for the consequences of use of this
  103. X *    software, no matter how awful, even if they arise from flaws in it.
  104. X *
  105. X * 2. The origin of this software must not be misrepresented, either by
  106. X *    explicit claim or by omission.  Since few users ever read sources,
  107. X *    credits must appear in the documentation.
  108. X *
  109. X * 3. Altered versions must be plainly marked as such, and must not be
  110. X *    misrepresented as being the original software.  Since few users
  111. X *    ever read sources, credits must appear in the documentation.
  112. X *
  113. X * 4. This notice may not be removed or altered.
  114. X */
  115. X
  116. X /*
  117. X  * This notice is copied from that included with cnews, which was
  118. X  * written (mostly) by Geoffrey Collyer and Henry Spencer.
  119. X  */
  120. END_OF_FILE
  121. if test 1026 -ne `wc -c <'COPYRIGHT'`; then
  122.     echo shar: \"'COPYRIGHT'\" unpacked with wrong size!
  123. fi
  124. # end of 'COPYRIGHT'
  125. fi
  126. if test -f 'Makefile' -a "${1}" != "-c" ; then 
  127.   echo shar: Will not clobber existing file \"'Makefile'\"
  128. else
  129. echo shar: Extracting \"'Makefile'\" \(129 characters\)
  130. sed "s/^X//" >'Makefile' <<'END_OF_FILE'
  131. XCC = gcc -Wall
  132. XCFLAGS = -O # -DDEBUG
  133. XLDFLAGS = # -shlib
  134. X
  135. Xpackdisk: packdisk.o
  136. X    $(CC) $(CFLAGS) $(LDFLAGS) -o packdisk packdisk.o
  137. END_OF_FILE
  138. if test 129 -ne `wc -c <'Makefile'`; then
  139.     echo shar: \"'Makefile'\" unpacked with wrong size!
  140. fi
  141. # end of 'Makefile'
  142. fi
  143. if test -f 'packdisk.c' -a "${1}" != "-c" ; then 
  144.   echo shar: Will not clobber existing file \"'packdisk.c'\"
  145. else
  146. echo shar: Extracting \"'packdisk.c'\" \(11393 characters\)
  147. sed "s/^X//" >'packdisk.c' <<'END_OF_FILE'
  148. X/*
  149. X *
  150. X * This program takes a disk and makes all the files and directories,
  151. X * and the free list, contiguous.
  152. X *
  153. X *                         Andrew Fyfe
  154. X *                        7 October 1989
  155. X *
  156. X *                        andy@csvax.caltech.edu
  157. X */
  158. X
  159. X#include <sys/filsys.h>
  160. X#include <sys/ino.h>
  161. X#include <sys/stat.h>
  162. X#include <stdio.h>
  163. X#include <stdlib.h>
  164. X
  165. X#define NUM_ADDR    13
  166. X#define FIRST_INDIR    10   /* 0-9 direct, 10 single, 11 double, 12 triple */
  167. X#define NUM_INDIR    (NUM_ADDR - FIRST_INDIR)
  168. X
  169. Xchar *cmd_name;
  170. Xint disk, dev;
  171. X
  172. Xstruct filsys filsys;
  173. X
  174. Xstruct dinode ino;    /* current working inode, and its number */
  175. Xino_t w_ino;
  176. X
  177. Xchar *inode_block;    /* block containing last read/written inode */
  178. Xdaddr_t w_ino_blk;    /* and its number */
  179. X
  180. Xchar *indir[NUM_INDIR];        /* current working indirect blocks */
  181. Xdaddr_t w_indir[NUM_INDIR];    /* and their numbers */
  182. X
  183. Xdaddr_t next_fill;    /* next (sequential) block to fill */
  184. X
  185. Xchar *inode_table;    /* a cache of the entire inode section of the disk */
  186. X
  187. Xlong *map;    /* a map from block numbers to referencing inode/indir block */
  188. X
  189. Xstatic void read_superblk(void);
  190. Xstatic void write_superblk(void);
  191. Xstatic void map_inode(ino_t inode);
  192. Xstatic void update_map(long map_entry, daddr_t block, int level);
  193. Xstatic void read_block(daddr_t block, void *buf);
  194. Xstatic void write_block(daddr_t block, void *buf);
  195. Xstatic void read_inode(ino_t inode, struct dinode *buf);
  196. Xstatic void write_inode(ino_t inode, struct dinode *buf);
  197. Xstatic void move_block(daddr_t from, daddr_t to);
  198. Xstatic void move_inode(ino_t inode);
  199. Xstatic void move_indirect(daddr_t block, int level);
  200. Xstatic void make_hole(void);
  201. Xstatic void rebuild_free_list(void);
  202. X
  203. Xextern void l3tol(long *, char *, int length);
  204. Xextern void ltol3(char *, long *, int length);
  205. X
  206. Xvoid
  207. Xmain(int argc, char *argv[])
  208. X{
  209. X    ino_t inode, total_inodes;
  210. X    daddr_t block;
  211. X    int i;
  212. X    char *ctime(long *);
  213. X#ifndef DEBUG
  214. X    struct stat statb;
  215. X    extern int stat(const char *, struct stat *);
  216. X#endif
  217. X
  218. X    cmd_name = argv[0];
  219. X
  220. X    if (argc != 2) {
  221. X    fprintf(stderr, "%s: Usage: %s <file system>\n",
  222. X        cmd_name, cmd_name);
  223. X    exit(1);
  224. X    }
  225. X
  226. X#ifndef DEBUG
  227. X    if (stat(argv[1], &statb) < 0) {
  228. X    fprintf(stderr, "%s: can't stat %s: ", cmd_name, argv[1]);
  229. X    perror("");
  230. X    exit(1);
  231. X    }
  232. X    if ((statb.st_mode & S_IFMT) != S_IFCHR) {
  233. X    fprintf(stderr, "%s: %s is not a character device\n",
  234. X        cmd_name, argv[1]);
  235. X    exit(1);
  236. X    }
  237. X#endif
  238. X
  239. X    disk = open(argv[1], 2, 0);
  240. X    if (disk < 0) {
  241. X    fprintf(stderr, "%s: can't open %s: ", cmd_name, argv[1]);
  242. X    perror("");
  243. X    exit(1);
  244. X    }
  245. X
  246. X    read_superblk();
  247. X
  248. X    total_inodes = (filsys.s_isize - FsITOD(dev, ROOTINO)) * FsINOPB(dev);
  249. X    fprintf(stderr, "File system: name: \"%.6s\", pack: \"%.6s\"\n",
  250. X    filsys.s_fname, filsys.s_fpack);
  251. X    fprintf(stderr, "\tlast modified on %s", ctime(&filsys.s_time));
  252. X    fprintf(stderr,
  253. X    "\ttotal inodes = %d, data blocks = %d, total = %d blocks\n",
  254. X    total_inodes, filsys.s_fsize - filsys.s_isize, filsys.s_fsize);
  255. X    fprintf(stderr, "\tfree blocks = %d, free inodes = %d\n",
  256. X    filsys.s_tfree, filsys.s_tinode);
  257. X
  258. X    for (i = 0; i < NUM_INDIR; ++i) {
  259. X    w_indir[i] = 0;
  260. X    indir[i] = malloc(FsBSIZE(dev));
  261. X    if (indir[i] == 0) {
  262. X        fprintf(stderr, "%s: can't malloc indir buffer space: ", cmd_name);
  263. X        perror("");
  264. X        exit(1);
  265. X    }
  266. X    }
  267. X    w_ino = 0;
  268. X
  269. X    map = calloc(filsys.s_fsize, sizeof(*map));
  270. X    if (map == 0) {
  271. X    fprintf(stderr, "%s: can't calloc map: ", cmd_name);
  272. X    perror("");
  273. X    exit(1);
  274. X    }
  275. X
  276. X    inode_table = malloc(filsys.s_isize * FsBSIZE(dev));
  277. X    if (inode_table == 0) {
  278. X    fprintf(stderr, "%s: can't malloc space for inode table\n", cmd_name);
  279. X    w_ino_blk = 0;
  280. X    inode_block = malloc(FsBSIZE(dev));
  281. X    if (inode_block == 0) {
  282. X        fprintf(stderr, "%s: can't malloc inode buffer space: ", cmd_name);
  283. X        perror("");
  284. X        exit(1);
  285. X    }
  286. X    }
  287. X    else
  288. X    for (block = FsITOD(dev, ROOTINO); block < filsys.s_isize; ++block)
  289. X        read_block(block, &inode_table[block * FsBSIZE(dev)]);
  290. X
  291. X    fprintf(stderr, "mapping...");
  292. X    for (inode = ROOTINO; inode <= total_inodes; ++inode)
  293. X    map_inode(inode);
  294. X    fprintf(stderr, "done\n");
  295. X
  296. X    next_fill = filsys.s_isize;
  297. X    for (inode = ROOTINO; inode <= total_inodes; ++inode)
  298. X    move_inode(inode);
  299. X
  300. X    fprintf(stderr, "\nrebuilding the free list\n");
  301. X    rebuild_free_list();
  302. X
  303. X    fprintf(stderr, "*** Run fsck to check out the disk!!!\n");
  304. X
  305. X    close(disk);
  306. X    exit(0);
  307. X}
  308. X
  309. Xstatic void
  310. Xread_superblk(void)
  311. X{
  312. X    if (lseek(disk, SUPERBOFF, 0) != SUPERBOFF) {
  313. X    fprintf(stderr, "%s: can't seek to superblock: ", cmd_name);
  314. X    perror("");
  315. X    exit(1);
  316. X    }
  317. X    if (read(disk, &filsys, sizeof(filsys)) != sizeof(filsys)) {
  318. X    fprintf(stderr, "%s: can't read superblock: ", cmd_name);
  319. X    perror("");
  320. X    exit(1);
  321. X    }
  322. X    if (filsys.s_magic != FsMAGIC) {
  323. X    fprintf(stderr, "%s: invalid superblock magic number\n", cmd_name);
  324. X    exit(1);
  325. X    }
  326. X    dev = (filsys.s_type == Fs2b) ? Fs2BLK : 0;
  327. X}
  328. X
  329. Xstatic void
  330. Xwrite_superblk(void)
  331. X{
  332. X    lseek(disk, SUPERBOFF, 0);
  333. X    if (write(disk, &filsys, sizeof(filsys)) != sizeof(filsys)) {
  334. X    fprintf(stderr, "%s: can't write superblock: ", cmd_name);
  335. X    perror("");
  336. X    exit(1);
  337. X    }
  338. X}
  339. X
  340. Xstatic void
  341. Xmap_inode(ino_t inode)
  342. X{
  343. X    int type, i;
  344. X    long block[NUM_ADDR];
  345. X
  346. X    read_inode(inode, &ino);
  347. X    if (ino.di_mode == 0)
  348. X    return;
  349. X    type = ino.di_mode & S_IFMT;
  350. X    if (type == S_IFCHR || type == S_IFBLK)
  351. X    return;
  352. X
  353. X    l3tol(block, ino.di_addr, NUM_ADDR);
  354. X    for (i = 0; i < NUM_ADDR; ++i)
  355. X    if (block[i] != 0)
  356. X        update_map(inode, block[i],
  357. X        (i < FIRST_INDIR) ? 0 : (i - FIRST_INDIR + 1));
  358. X}
  359. X
  360. Xstatic void
  361. Xupdate_map(long map_entry, daddr_t block, int level)
  362. X{
  363. X    int i;
  364. X
  365. X    if (map[block] != 0) {
  366. X    fprintf(stderr, "%s: duplicate block %d in %d and %d\n",
  367. X        cmd_name, block, map[block], map_entry);
  368. X    exit(1);
  369. X    }
  370. X    map[block] = map_entry;
  371. X
  372. X    if (level == 0)
  373. X    return;
  374. X
  375. X    --level;
  376. X    read_block(block, indir[level]);
  377. X    for (i = 0; i < FsNINDIR(dev); ++i)
  378. X    if (((daddr_t *)indir[level])[i] != 0)
  379. X        update_map(-block, ((daddr_t *)indir[level])[i], level);
  380. X}
  381. X
  382. Xstatic void
  383. Xread_block(daddr_t block, void *buf)
  384. X{
  385. X    lseek(disk, block * FsBSIZE(dev), 0);
  386. X    if (read(disk, buf, FsBSIZE(dev)) != FsBSIZE(dev)) {
  387. X    fprintf(stderr, "%s: can't read block %d: ", cmd_name, block);
  388. X    perror("");
  389. X    exit(1);
  390. X    }
  391. X}
  392. X
  393. Xstatic void
  394. Xwrite_block(daddr_t block, void *buf)
  395. X{
  396. X    lseek(disk, block * FsBSIZE(dev), 0);
  397. X    if (write(disk, buf, FsBSIZE(dev)) != FsBSIZE(dev)) {
  398. X    fprintf(stderr, "%s: can't write block %d: ", cmd_name, block);
  399. X    perror("");
  400. X    exit(1);
  401. X    }
  402. X}
  403. X
  404. Xstatic void
  405. Xread_inode(ino_t inode, struct dinode *ino)
  406. X{
  407. X    daddr_t block;
  408. X
  409. X    block = FsITOD(dev, inode);
  410. X    if (inode_table == 0) {
  411. X    if (w_ino_blk != block) {
  412. X        w_ino_blk = block;
  413. X        read_block(block, inode_block);
  414. X    }
  415. X    *ino = ((struct dinode *)inode_block)[FsITOO(dev, inode)];
  416. X    }
  417. X    else {
  418. X    *ino = ((struct dinode *)&inode_table[block * FsBSIZE(dev)])
  419. X        [FsITOO(dev, inode)];
  420. X    }
  421. X}
  422. X
  423. Xstatic void
  424. Xwrite_inode(ino_t inode, struct dinode *ino)
  425. X{
  426. X    daddr_t block;
  427. X
  428. X    block = FsITOD(dev, inode);
  429. X    if (inode_table == 0) {
  430. X    if (w_ino_blk != block) {
  431. X        w_ino_blk = block;
  432. X        read_block(block, inode_block);
  433. X    }
  434. X    ((struct dinode *)inode_block)[FsITOO(dev, inode)] = *ino;
  435. X    write_block(block, inode_block);
  436. X    }
  437. X    else {
  438. X    ((struct dinode *)&inode_table[block * FsBSIZE(dev)])
  439. X        [FsITOO(dev, inode)] = *ino;
  440. X    write_block(block, &inode_table[block * FsBSIZE(dev)]);
  441. X    }
  442. X}
  443. X
  444. Xstatic void
  445. Xmove_block(daddr_t from, daddr_t to)
  446. X{
  447. X    char buffer[FsBSIZE(dev)];
  448. X    daddr_t block;
  449. X
  450. X    if (map[to] != 0)
  451. X    make_hole();
  452. X
  453. X    read_block(from, buffer);
  454. X    write_block(to, buffer);
  455. X
  456. X    map[to] = map[from];
  457. X    map[from] = 0;
  458. X
  459. X    for (block = filsys.s_isize; block < filsys.s_fsize; ++block)
  460. X    if (map[block] == -from)
  461. X        map[block] = -to;
  462. X}
  463. X
  464. Xstatic void
  465. Xmove_inode(ino_t inode)
  466. X{
  467. X    int type, i;
  468. X    long block[NUM_ADDR];
  469. X
  470. X    read_inode(inode, &ino);
  471. X    w_ino = inode;
  472. X    if (ino.di_mode == 0)
  473. X    return;
  474. X    type = ino.di_mode & S_IFMT;
  475. X    if (type == S_IFCHR || type == S_IFBLK)
  476. X    return;
  477. X    
  478. X    fprintf(stderr, "moving inode %d (size %d)                         \r",
  479. X    inode, ino.di_size);
  480. X
  481. X    l3tol(block, ino.di_addr, NUM_ADDR);
  482. X    for (i = 0; i < NUM_ADDR; ++i) {
  483. X    if (block[i] == 0)
  484. X        continue;
  485. X    if (block[i] != next_fill) {
  486. X        move_block(block[i], next_fill);
  487. X        l3tol(block, ino.di_addr, NUM_ADDR);
  488. X        block[i] = next_fill;
  489. X        ltol3(ino.di_addr, block, NUM_ADDR);
  490. X        write_inode(inode, &ino);
  491. X    }
  492. X    ++next_fill;
  493. X    }
  494. X    
  495. X    for (i = FIRST_INDIR; i < NUM_ADDR; ++i)
  496. X    move_indirect(block[i], i-FIRST_INDIR);
  497. X}
  498. X
  499. Xstatic void
  500. Xmove_indirect(daddr_t block, int level)
  501. X{
  502. X    int i;
  503. X
  504. X    if (block == 0)
  505. X    return;
  506. X
  507. X    read_block(block, indir[level]);
  508. X    w_indir[level] = block;
  509. X
  510. X    for (i = 0; i < FsNINDIR(dev); ++i) {
  511. X    if (((daddr_t *)indir[level])[i] == 0)
  512. X        continue;
  513. X    if (((daddr_t *)indir[level])[i] != next_fill) {
  514. X        move_block(((daddr_t *)indir[level])[i], next_fill);
  515. X        ((daddr_t *)indir[level])[i] = next_fill;
  516. X        write_block(block, indir[level]);
  517. X    }
  518. X    ++next_fill;
  519. X    }
  520. X
  521. X    if (level == 0)
  522. X    return;
  523. X
  524. X    for (i = 0; i < FsNINDIR(dev); ++i)
  525. X    move_indirect(((daddr_t *)indir[level])[i], level-1);
  526. X}
  527. X
  528. Xstatic void
  529. Xmake_hole(void)
  530. X{
  531. X    char t_indir[FsBSIZE(dev)];
  532. X    daddr_t *p_indir;
  533. X    struct dinode t_ino, *p_ino;
  534. X    long block[NUM_ADDR];
  535. X    daddr_t back;
  536. X    int i;
  537. X
  538. X    back = filsys.s_fsize - 1;
  539. X    while (next_fill < back && map[back] != 0)
  540. X    --back;
  541. X
  542. X    if (next_fill >= back) {
  543. X    fprintf(stderr, "%s: can't find a free block for %d\n",
  544. X        cmd_name, next_fill);
  545. X    exit(1);
  546. X    }
  547. X
  548. X    move_block(next_fill, back);
  549. X
  550. X    if (map[back] < 0) {
  551. X    block[0] = -map[back];
  552. X    for (i = 0; i < NUM_INDIR; ++i)
  553. X        if (block[0] == w_indir[i])
  554. X        break;
  555. X    if (i < NUM_INDIR) {
  556. X        p_indir = (daddr_t *)indir[i];
  557. X    }
  558. X    else {
  559. X        p_indir = (daddr_t *)t_indir;
  560. X        read_block(block[0], t_indir);
  561. X    }
  562. X    for (i = 0; i < FsNINDIR(dev); ++i) {
  563. X        if (p_indir[i] == next_fill) {
  564. X        p_indir[i] = back;
  565. X        break;
  566. X        }
  567. X    }
  568. X    if (i == FsNINDIR(dev)) {
  569. X        fprintf(stderr,
  570. X        "%s: panic: can't find %d in indirect block %d\n",
  571. X        cmd_name, next_fill, -map[back]);
  572. X        exit(1);
  573. X    }
  574. X    write_block(block[0], p_indir);
  575. X    }
  576. X    else {
  577. X    if (map[back] == w_ino) {
  578. X        p_ino = &ino;
  579. X    }
  580. X    else {
  581. X        p_ino = &t_ino;
  582. X        read_inode(map[back], &t_ino);
  583. X    }
  584. X    l3tol(block, p_ino->di_addr, NUM_ADDR);
  585. X    for (i = 0; i < NUM_ADDR; ++i) {
  586. X        if (block[i] == next_fill) {
  587. X        block[i] = back;
  588. X        ltol3(p_ino->di_addr, block, NUM_ADDR);
  589. X        break;
  590. X        }
  591. X    }
  592. X    if (i == NUM_ADDR) {
  593. X        fprintf(stderr, "%s: panic: can't find %d in inode %d\n",
  594. X        cmd_name, next_fill, map[back]);
  595. X        exit(1);
  596. X    }
  597. X    write_inode(map[back], p_ino);
  598. X    }
  599. X}
  600. X
  601. Xstatic void
  602. Xrebuild_free_list(void)
  603. X{
  604. X    int free_size, nfree;
  605. X    daddr_t free[NICFREE], block;
  606. X    char buf[FsBSIZE(dev)];
  607. X
  608. X    free_size = filsys.s_fsize - next_fill;
  609. X    if (free_size != filsys.s_tfree) {
  610. X    fprintf(stderr, "%s: free list changed size from %d to %d\n",
  611. X        cmd_name, filsys.s_tfree, free_size);
  612. X    exit(1);
  613. X    }
  614. X
  615. X    nfree = 1;
  616. X    memset(free, 0, sizeof(free));
  617. X    memset(buf, 0, sizeof(buf));
  618. X
  619. X    for (block = filsys.s_fsize - 1; block >= next_fill; --block) {
  620. X    if (nfree == NICFREE) {
  621. X        ((daddr_t *)buf)[0] = nfree;
  622. X        memcpy(&((daddr_t *)buf)[1], free, sizeof(free));
  623. X        write_block(block, buf);
  624. X        nfree = 0;
  625. X        memset(free, 0, sizeof(free));
  626. X    }
  627. X    free[nfree++] = block;
  628. X    }
  629. X
  630. X    filsys.s_nfree = nfree;
  631. X    memcpy(&filsys.s_free, free, sizeof(free));
  632. X    write_superblk();
  633. X}
  634. END_OF_FILE
  635. if test 11393 -ne `wc -c <'packdisk.c'`; then
  636.     echo shar: \"'packdisk.c'\" unpacked with wrong size!
  637. fi
  638. # end of 'packdisk.c'
  639. fi
  640. echo shar: End of shell archive.
  641. exit 0
  642.  
  643.